public without sharing class TransferProductController {

    public Map<String,SObjectType> objMap;//全局对象

    public String selectedObj {get;set;}//选择的对象

    // 对象一览
    // 选中的对象API名

    public Integer dataCount {get; private set;}

    public Integer limitCount {get;set;}

    public String msg {get; private set;}

    public String coutsql ;

    public String searchObjctStr {get;set;}
    public String dataJson {get; private set;}


    public TransferProductController() {

      
        objMap = new Map<String, SObjectType>();


        dataCount = 0;
        limitCount = 200;
        coutsql = '';
        msg = '';

     
    }

    public void init() {
        getGlobalObjects();
    }
    public void getGlobalObjects(){
        ///获取所有对象
        for(Schema.sobjecttype s: Schema.getGlobalDescribe().values()){
                //选择自定义对象//&& s.getDescribe().isSearchable() == true
                if(s.getDescribe().isSearchable() == true) {
                    //保存
                    objMap.put(s.getDescribe().getName(),s);
                }

        }

    }

    public void searchObjName(){
        dataJson = '[]';
        String s = searchObjctStr == null ? null : EncodingUtil.urlDecode(searchObjctStr, 'UTF-8');

        List<Object> tmp = new List<Object>();

        if(s == null )return;

        for (String sobjectName  : objMap.keySet() ) {
            SObjectType stype = objMap.get(sobjectName);
            if(sobjectName.contains(s)  || stype.getDescribe().getLabel().contains(s)){
                Map<String,Object> m = new Map<String,Object>();
                m.put('id', sobjectName);
                m.put('text', stype.getDescribe().getLabel());
                m.put('releated', getRelatedSObject1(stype));
                tmp.add(m);
            }
        }
        dataJson = EncodingUtil.urlEncode( JSON.serialize( tmp), 'UTF-8');

    }


    private List<Object> getRelatedSObject1(SObjectType st ){
       
        // 动态获取所有参照了【st】的对象，及其参照字段
        List<Object> tmp = new List<Object>();
        Schema.DescribeSObjectResult R = st.getDescribe();
        List<Schema.ChildRelationship> C = R.getChildRelationships();
        for (Schema.ChildRelationship child  : C) {
            //String fieldLabel = child.getField().getDescribe().getLabel();
            String fieldApi = child.getField().getDescribe().getName();
            String objLabel = child.getChildSObject().getDescribe().getLabel();
            String objApi = child.getChildSObject().getDescribe().getName();
            // 除去SF系统对象，系统对象的参照字段不带__c
            if (fieldApi.endsWith('__c')) {
                
                Map<String,String> m = new Map<String,String>();
                m.put('id',objApi + '!'+fieldApi );
                m.put('text', objLabel +'  字段: ' +fieldApi);
                tmp.add(m);
            }
        }
        return tmp;
        
    }  

    public void transfer2(){
        msg = '';
        Savepoint sp = Database.setSavepoint();
        try {
            
            Map<String,Object>searchMap =(Map<String,Object>) JSON.deserializeUntyped(EncodingUtil.urlDecode(searchObjctStr,'UTF-8'));
             List<Object> saveList  = (List<Object>)searchMap.get('data');
            // 动态拼接SOQL
            String newObjId =  (String)searchMap.get('newId');
             String objApi = (String)searchMap.get('objApi');

            if(String.isBlank(objApi))throw new DmlException('转移关联对象不能为空!');
            if(String.isBlank(newObjId))throw new DmlException('新ID不能为空!');
                List<String> sObField = objApi.split('!');

                List<SObject> uList = new List<SObject>();
                for (Object o  : saveList ) {
                    Map<String,Object>mo = (Map<String,Object>)o ;
                    SObjectType stype= objMap.get(sObField[0]);
                    if(stype == null)throw new DmlException('没有找到对象:'+sObField[0]);
                    SObject so = stype.newSObject();

                    so.put(sObField[1], newObjId);
                    so.put('Id',mo.get('id'));

                    uList.add(so);
                }
                if(!uList.isEmpty())update uList;
                msg ='转移成功!';

        }catch (Exception e) {
            Database.rollback(sp);
            msg = e.getMessage();
        }
    }
    public void transfer1(){
        msg = '';
        Savepoint sp = Database.setSavepoint();
        try {
            
            Map<String,Object>searchMap =(Map<String,Object>) JSON.deserializeUntyped(EncodingUtil.urlDecode(searchObjctStr,'UTF-8'));
             String objApi = (String)searchMap.get('objApi');
            // 动态拼接SOQL
            String oldObjId  = (String)searchMap.get('oldId');
            String newObjId =  (String)searchMap.get('newId');
            String lmt = (String)searchMap.get('limit');
            if(String.isNotBlank(lmt))limitCount = Integer.valueOf(lmt);

            if(String.isBlank(objApi))throw new DmlException('转移关联对象不能为空!');
            if(String.isBlank(oldObjId))throw new DmlException('旧ID不能为空!');
            if(String.isBlank(newObjId))throw new DmlException('新ID不能为空!');
            String cntSql = getCntSql(objApi,oldObjId,true );

            Integer cnt =  database.countquery(cntSql);
            if(cnt > 0 ){
                List<SObject> uList = new List<SObject>();
                for (SObject so  :Database.query(getCntSql(objApi,oldObjId,false )) ) {
                    so.put(objApi.split('!')[1], newObjId);
                    uList.add(so);
                }
                if(!uList.isEmpty())update uList;
                msg =String.valueOf( cnt - limitCount);

            }else{
                msg = '-1';
            }

        }catch (Exception e) {
            Database.rollback(sp);
            msg = e.getMessage();
        }
    
        
    }

    private String  getCntSql(String objApi, String oldObjId ,Boolean isCnt ){
        //String fieldInfo = objApi;
        //需要转移的对象
         String ffield  = objApi.split('!')[1];
        String fApi = objApi.split('!')[0];
        if(isCnt)return  'select count()  from '+ fApi + ' where ' +  ffield + ' = \'' + oldObjId+ '\' ';
        
        String sql = 'select Id, Name ';
        Boolean isCase =  fApi.toUpperCase() == 'CASE';
        if(isCase)sql = 'select Id ,CaseNumber ';
        sql +=  ' from ' + fApi + ' where ' +  ffield + ' = \'' + oldObjId+ '\' ' + ' limit ' + limitCount;
        return sql;

    }
      public void searchData() {
        List<RelateBean> tmp  = new List<RelateBean>();

        Map<String,Object>searchMap =(Map<String,Object>) JSON.deserializeUntyped(EncodingUtil.urlDecode(searchObjctStr,'UTF-8'));

        
        String objApi = (String)searchMap.get('objApi');
        // 动态拼接SOQL
        String oldObjId  = (String)searchMap.get('oldId');
        
        //String fieldInfo = objApi;
        //需要转移的对象
        String objApi1 = (String)searchMap.get('objApi');
         String ffield  = objApi1.split('!')[1];
        String fApi = objApi1.split('!')[0];
        
        
        String sql = 'select Id, Name ';
       Boolean isCase =  fApi.toUpperCase() == 'CASE';
       if(isCase)sql = 'select Id ,CaseNumber ';
    

        sql +=  ' from ' + fApi + ' where ' +  ffield + ' = \'' + oldObjId+ '\' ' + ' limit ' + limitCount;
        //System.debug(sql);

        coutsql = 'select count()  from '+ fApi + ' where ' +  ffield + ' = \'' + oldObjId+ '\' ';
       // System.debug(coutsql);

        dataCount = database.countquery(coutsql);
        for (SObject s : Database.query(sql)) {
            tmp.add(new RelateBean(s,isCase));
        }
        Map<String,Object>  data = new Map<String,Object>();
        data.put('data', tmp);
        data.put('count', dataCount);
        dataJson = EncodingUtil.urlEncode( JSON.serialize( data), 'UTF-8');
    }

    public class RelateBean {
        public String id ;
        public String name ;
        public RelateBean(SObject s,Boolean isCase ) {
            id = String.valueOf(s.get('Id'));
            name = isCase  ? String.valueOf(s.get('CaseNumber')): String.valueOf(s.get('Name'));
        }
    }
   
   

    
}